<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="google-site-verification" content="yaeorbXgKPwp5BDegBtAJEHYWFEFE-BViWTj74gJPrw" />
<!--  -->
<link href="/css/default.css" type="text/css" rel="stylesheet" />
<!--  -->
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/lang/en.js"></script>
<script type="text/javascript" src="/js/mac/core.min.js"></script>
<title>mac-rpc 远程方法调用框架</title>
<meta name="description" content="RPC框架 远程方法调用框架 微服务框架" />
<meta name="keywords" content="RPC 远程方法调用  微服务 框架 mac-rpc" />
<script type="text/javascript">
$(function(){
	function adjust(){
		var de = document.documentElement
			, ch = de.clientHeight, cw = de.clientWidth;
		$('#body').width(cw - 16);
	}
	$(window).resize(adjust);
	adjust();
});
</script>
</head>
<body>
<div id="head">
	<a href="/en/"><img src="/css/images/logo_s.png" alt="logo" /></a>
	<div class="title">BOARSOFT.COM</div>
	<div class="right">
		<div>
			<a href="/public/lang.php?l=en">English</a>
			|
			<a href="/public/lang.php?l=cn">简体中文</a>
			|
			<a href="http://activemq.apache.org/" target="_blank">ActiveMQ</a>
			|
			<a href="https://redis.io/" target="_blank">Redis</a>
			|
			<a href="http://www.jquery.com/" target="_blank">JQuery</a>
		</div>
	</div>
</div><div id="body">
	<div class="dir">
<h1>目录</h1>
<hr/>
<ul>
	<li><a href="./index.html">基本概念</a></li>
	<ul>
		<li><a href="./index.html#node">服务消费者与提供者</a></li>
		<li><a href="./index.html#svc">服务四要素</a></li>
		<li><a href="./index.html#reg">服务注册与发现</a></li>
		<li><a href="./index.html#call">服务调用过程</a></li>
	</ul>
	<li><a href="./config.html">配置说明</a></li>
	<ul>
		<li><a href="./config.html#basic">基本配置</a></li>
		<li><a href="./config.html#registry">注册中心配置</a></li>
		<li><a href="./config.html#provider">服务提供者配置</a></li>
		<li><a href="./config.html#consume">服务消费者配置</a></li>
	</ul>
	<li><a href="./demo.html#">用法示例</a><li>
	<ul>
		<li><a href="./demo.html">同步调用</a></li>
		<li><a href="./demo.html#sc">指定服务提供者</a></li>
		<li><a href="./demo.html#ac">异步调用</a></li>
		<li><a href="./demo.html#sb">同步广播方法</a></li>
		<li><a href="./demo.html#ab">异步广播方法</a></li>
	</ul>
	<li><a href="./console.html">RPC管控</a><li>
	<ul>
		<li><a href="./console.html#node">节点视图</a></li>
		<li><a href="./console.html#svc">服务视图</a></li>
		<li><a href="./console.html#status"></a>开关</li>
		<li><a href="./console.html#limit"></a>限流</li>
		<li><a href="./console.html#toggle"></a>升降级</li>
	</ul>
	<li><a href="./advance.html">进阶应用</a><li>
	<ul>
		<li><a href="./advance.html#seriallize">自定义序列化器</a></li>
		<li><a href="./advance.html#protocal">自定义传输协议</a></li>
		<li><a href="./advance.html#threadpool">自定义线程池</a></li>
		<li><a href="./advance.html#tune">性能调优</a></li>
		<li><a href="./advance.html#more">更多可能</a></li>
	</ul>
	<li><a href="./qa.html">常见问题</a></li>
</ul>	</div>
	<div class="main">
		<div id="nav">
			<div id="nav_path">
				<a href="/en/">Home</a>
				&gt;
				mac-rpc
			</div>
			<div id="nav_back">
				<a href="javascript:history.back()">Back</a>
				|
				<a href="/en/">UP</a> &nbsp;&nbsp;
			</div>
			<div class="clear"></div>
		</div>
<h1>mac-rpc 全异步高性能RPC框架</h1>
<h2>基本概念</h2>
&nbsp;&nbsp;mac-rpc是基于Java AIO开发的全异步、高性能RPC（远程方法调用）框架，它没有使用Netty等第三方网络通讯组件，则是从底层的网络通讯写起，采用了类似事件驱动的远程调用机制，能够减少了阻塞和线程切换开销，提高CPU的使用效率。这使得mac-rpc有着优异的性能表现和与众不同的能力，尤其是在对异步方法调用的支持上。<br/>
&nbsp;&nbsp;优秀的设计使得mac-rpc十会的简洁优雅，在实现强大功能的同时，保持了小巧灵活的特点、极具扩展性，允许定制传输协议、序列化方式等。<br/>
&nbsp;&nbsp;注：mac-rpc标配使用hessian作为序列化组件（可替换，包括去除依赖）<br/>
&nbsp;&nbsp;在使用上，除了必须依赖 spring外（core,beans,context,aop）实现了对应用的“零侵入”。
<h3><a name="svc"></a>服务四要素</h3>
&nbsp;&nbsp;以下四个要素用以确定一个服务：
<ul>
	<li>group：服务的分组</li>
	<li>name：服务的名称或编号</li>
	<li>interface：服务的接口</li>
	<li>version：服务的版本</li>
</ul>
<h3><a name="node"></a>服务消费者与提供者</h3>
&nbsp;&nbsp;在基于远程方法调用（RPC）的微服务架构设计理念中，一个可供远程调用的方法即被视为一个服务，远程方法调用的发起方（调用方）就是这一服务的消费者（Consumer），被调用方（服务方）就是这一服务的提供者（Provider）。<br/>
&nbsp;&nbsp;通常一个应用可能会暴露多个可供远程调用的方法，也可能会需要调用多个远程方法。这要求本地应用持有这些远程方法的本地引用。MAC-RPC采用JAVA的动态代理机制，为每一个需要引用的远程方法在本地动态创建对应的“引用”——动态代理对象（Proxy）。<br/>
&nbsp;&nbsp;应用是服务的“容器”，应用的实例被称为节点（Node）。<br/>
<h3><a name="reg"></a>服务注册与发现</h3>
&nbsp;&nbsp;在基于MAC-RPC的微服务环境中，一个应用的一个实例就是一个节点。节点之间通过一个叫做“注册中心”地方交换服务信息，实现服务层面的服务注册与发现。<br/>
&nbsp;&nbsp;MAC-RPC采用所谓的“弱中心化”设计，任何一个节点均可以被标记为主节点（master）,而主节点在MAC-RPC中就扮演了服务的注册中心的角色，并且可以有多个。
&nbsp;&nbsp;普通的RPC节点连接到其中任意一个master节点就可以与其它所有节点连通。<br/>
&nbsp;&nbsp;所节点都通过主节点进行注册表交换，过程如下：
<ol>
	<li>所有节点将自身的注册信息（注册表）提交到它的主节点（可能是N3，也可能是N4）。</li>
	<li>由该主节点将此注册表保存在内存中，并推送到所有与之连接的节点。注：一个普通节点只会连接一个主节点。</li>
	<li>各节点在收到推送后，判断是否比已持有的对应注册表更新，是则更新本地内存中的注册表。</li>
	<li>主节点在收到来自其它主节点的推送，且当收到的注册表比自己持有的更新时，会推送此注册表到与之连接的所有节点。</li>
</ol>
<h3><a name="call"></a>远程方法调用过程</h3>
&nbsp;&nbsp;在双方完成服务的注册与发现后，就可以通过远程调用彼此提供的方法。其间不再需要通过主节点。即使主节点宕机，也不受影响。<br/>
&nbsp;&nbsp;下图展示了节点N2调用N1提供的服务X的过程：</p>
<img alt="overview" src="/mac/rpc/img/overview.png" />
<ol>
	<li>Bean B获取Bean R的引用，并转换为X接口，调用其中的方法Y</li>
	<li>Bean R是RPC框架预先就动态创建好的类R的实例（对应consume.xml中的reference），它先根据配置的负载均衡算法挑出一个服务X提供者（N1）。再将本次方法调用封装为数据对象，交给RPC网络通讯层</li>
	<li>RPC通讯层将数据对象序列化、拆包，通过网络发送给N1</li>
	<li>N1的RPC通讯层负责接收这些数据包组包、还原，再反序列化后得到数据对象，确定要调用Bean S的对应方法。</li>
	<li>Bean S是为了不侵入目标Bean A，由RPC框架预先创建好了Bean A的代理类，框架通过它调用Bean A中的对应方法</li>
	<li>Bean A中的方法执行完毕后，将结果返回给Bean S（或抛出异常给Bean S捕获）</li>
	<li>调用完成后，由Bean S将返回的结果封装为数据对象，交给RPC网络通讯层</li>
	<li>N1的RPC网络通讯层将数据对象序列化、拆包，通过网络发送给N2</li>
	<li>N2的RPC网络通讯层将这些数据包组包、还原，再反序列化后得到数据对象，交给Bean R</li>
	<li>Bean R从数据对象中提出返回信息，包括调用结果和异常信息，作为方法调用的结果返回</li>
</ol>
<h3><a name="async"></a>方法调用类型</h3>
&nbsp;&nbsp;mac-rpc支持以下方法调用类型：
<ol start="0">
	<li>同步方法（SC）：调用方在调起远程方法后阻塞，等待远程方法的返回</li>
	<li>异步方法（AC）：异步调用方法的返回类型必须声明为Object，在编写实现时，需要返回真实的结果。但调用方在调用时获得的是一个Future&lt;Object&gt;</li>
	<li>同步通知（SN）：调用远程方法，对方会开始异步执行，并立即返回一个签收应答。</li>
	<li>异步通知（AN）：异步通知方法的返回类型必须声明为Object。服务方在收到请求后，会开始异步执行，并立即返回一个签收应答。而调用方调用远程方法，不会阻塞当前线，拿到的返回值是Future&lt;Object&gt;类型，调用其get方法时才会阻塞，以等待实际的返回值——来自服务方的签收应答。</li>
	<li>同步广播方法（SB）：也是是需要特殊处理的方法，其返回值必须是Object类型。在编写服务方的实现时，需要返回真实的结果。但在服务的调用方（服务消费者）拿到的对象却是Map&lt;String, Object&gt;类型。此map的key是执行此方法的节点的地址，形如：IP:PORT，而map的value才是实际的结果。</li>
	<li>异步广播方法（AB）：异步广播方法与同步广播方法在处理上基本相同。异步广播方法采用Future模式，返回Map&lt;String, Future&lt;Object&gt;&gt;，因此在获取实际结果前不会阻塞当前线程。</li>
	<li>广播通知方法（BN）：广播通知与异步广播方法在处理上相近。不同之处在于，服务端在收到请求后，不是同步执行，返回执行结果，而是异步执行，并立即返回签收应答。调用方拿到的返回值也是Map&lt;String, Future&lt;Object&gt;&gt;类型，只是从Future中get的只是签收应答，而不是远程方法的实际执行结果。</li>
</ol>
	</div>
</div>
<div id="foot">
Copyright © 2011. All rights reserved&nbsp;&nbsp;蜀ICP备11014774号-1&nbsp;&nbsp;
QQ: 7213571&nbsp;&nbsp;E-mail: pyh_jerry@163.com&nbsp;&nbsp;
<!-- 
<script type="text/javascript">
var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3Ffc0b0282216be3d16055855d8c0e72d9' type='text/javascript'%3E%3C/script%3E"));
</script>
&nbsp;&nbsp;
 -->
</div></body>
</html>
